#include "./kutils.h"
#include <QString>
#include <QStringList>
#include "qlib/utils/gds_utils.h"

namespace qbe::auxiliary {

//获取cell中所有基本图形
std::vector<entt::entity> getCellAllGraph(qlib::Cell::s_ptr cell) {
  std::vector<entt::entity> result;
  for (auto [e, p] : cell->reg.view<qlib::Polygon::s_ptr>().each()) {
    result.push_back(e);
  }
  for (auto [e, p] : cell->reg.view<qlib::Circle::s_ptr>().each()) {
    result.push_back(e);
  }
  for (auto [e, p] : cell->reg.view<qlib::Ellipse::s_ptr>().each()) {
    result.push_back(e);
  }
  for (auto [e, p] : cell->reg.view<qlib::Rectangle::s_ptr>().each()) {
    result.push_back(e);
  }
  for (auto [e, p] : cell->reg.view<qlib::Fan::s_ptr>().each()) {
    result.push_back(e);
  }
  for (auto [e, p] : cell->reg.view<qlib::Path::s_ptr>().each()) {
    result.push_back(e);
  }
  for (auto [e, p] : cell->reg.view<qlib::Label::s_ptr>().each()) {
    result.push_back(e);
  }
  for (auto [e, p] : cell->reg.view<qlib::KeyPoint::s_ptr>().each()) {
    result.push_back(e);
  }
  for (auto [e, p] : cell->reg.view<qlib::Pin::s_ptr>().each()) {
    result.push_back(e);
  }
  for (auto [e, p] : cell->reg.view<qlib::Text::s_ptr>().each()) {
    result.push_back(e);
  }
  for (auto [e, p] : cell->reg.view<qlib::Reference::s_ptr>().each()) {
    result.push_back(e);
  }
  return result;
}
//向cell中加入基本图形
std::vector<entt::entity> AddGraphToCell(qlib::Cell::s_ptr cell, std::vector<std::any> grpahs) {
  std::vector<entt::entity> result;
  for (auto g : grpahs) {
    const std::type_info& stored_type = g.type();
    if (stored_type == typeid(qlib::Polygon::s_ptr)) {
      qlib::Polygon::s_ptr poly = std::any_cast<qlib::Polygon::s_ptr>(g);
      auto e = cell->spawn(poly);
      result.push_back(e);
    } else if (stored_type == typeid(qlib::Circle::s_ptr)) {
      qlib::Circle::s_ptr circle = std::any_cast<qlib::Circle::s_ptr>(g);
      auto e = cell->spawn(circle);
      result.push_back(e);
    } else if (stored_type == typeid(qlib::Rectangle::s_ptr)) {
      qlib::Rectangle::s_ptr rec = std::any_cast<qlib::Rectangle::s_ptr>(g);
      auto e = cell->spawn(rec);
      result.push_back(e);
    } else if (stored_type == typeid(qlib::Ellipse::s_ptr)) {
      qlib::Ellipse::s_ptr elli = std::any_cast<qlib::Ellipse::s_ptr>(g);
      auto e = cell->spawn(elli);
      result.push_back(e);
    } else if (stored_type == typeid(qlib::Fan::s_ptr)) {
      qlib::Fan::s_ptr fan = std::any_cast<qlib::Fan::s_ptr>(g);
      auto e = cell->spawn(fan);
      result.push_back(e);
    } else if (stored_type == typeid(qlib::Path::s_ptr)) {
      qlib::Path::s_ptr line = std::any_cast<qlib::Path::s_ptr>(g);
      auto e = cell->spawn(line);
      result.push_back(e);
    } else if (stored_type == typeid(qlib::Label::s_ptr)) {
      qlib::Label::s_ptr lable = std::any_cast<qlib::Label::s_ptr>(g);
      auto e = cell->spawn(lable);
      result.push_back(e);
    } else if (stored_type == typeid(qlib::KeyPoint::s_ptr)) {
      qlib::KeyPoint::s_ptr key_point = std::any_cast<qlib::KeyPoint::s_ptr>(g);
      auto e = cell->spawn(key_point);
      result.push_back(e);
    } else if (stored_type == typeid(qlib::Pin::s_ptr)) {
      qlib::Pin::s_ptr pin = std::any_cast<qlib::Pin::s_ptr>(g);
      auto e = cell->spawn(pin);
      result.push_back(e);
    } else if (stored_type == typeid(qlib::Text::s_ptr)) {
      qlib::Text::s_ptr text = std::any_cast<qlib::Text::s_ptr>(g);
      auto e = cell->spawn(text);
      result.push_back(e);
    } else if (stored_type == typeid(qlib::Ruler::s_ptr)) {
      qlib::Ruler::s_ptr ruler = std::any_cast<qlib::Ruler::s_ptr>(g);
      auto e = cell->spawn(ruler);
      result.push_back(e);
    } else if (stored_type == typeid(qlib::Reference::s_ptr)) {
      qlib::Reference::s_ptr ref = std::any_cast<qlib::Reference::s_ptr>(g);
      auto e = cell->spawn(ref);
      result.push_back(e);
    }
  }
  return result;
}
std::vector<std::any> getGraph(qlib::Cell::s_ptr cell, std::vector<entt::entity> entities) {
  std::vector<std::any> result;

  for (auto e : entities) {
    {
      auto ptr = cell->reg.try_get<qlib::Polygon::s_ptr>(e);
      if (ptr) {
        auto poly = *ptr;
        result.push_back(poly);
      }
    }

    {
      auto ptr = cell->reg.try_get<qlib::Circle::s_ptr>(e);
      if (ptr) {
        auto circle = *ptr;
        result.push_back(circle);
      }
    }

    {
      auto ptr = cell->reg.try_get<qlib::Ellipse::s_ptr>(e);
      if (ptr) {
        auto elli = *ptr;
        result.push_back(elli);
      }
    }

    {
      auto ptr = cell->reg.try_get<qlib::Rectangle::s_ptr>(e);
      if (ptr) {
        auto rec = *ptr;
        result.push_back(rec);
      }
    }

    {
      auto ptr = cell->reg.try_get<qlib::Fan::s_ptr>(e);
      if (ptr) {
        auto fan = *ptr;
        result.push_back(fan);
      }
    }

    {
      auto ptr = cell->reg.try_get<qlib::Path::s_ptr>(e);
      if (ptr) {
        auto line = *ptr;
        result.push_back(line);
      }
    }

    {
      auto ptr = cell->reg.try_get<qlib::Label::s_ptr>(e);
      if (ptr) {
        auto label = *ptr;
        result.push_back(label);
      }
    }

    {
      auto ptr = cell->reg.try_get<qlib::KeyPoint::s_ptr>(e);
      if (ptr) {
        auto key_point = *ptr;
        result.push_back(key_point);
      }
    }

    {
      auto ptr = cell->reg.try_get<qlib::Pin::s_ptr>(e);
      if (ptr) {
        auto pin = *ptr;
        result.push_back(pin);
      }
    }

    {
      auto ptr = cell->reg.try_get<qlib::Ruler::s_ptr>(e);
      if (ptr) {
        auto ruler = *ptr;
        result.push_back(ruler);
      }
    }

    {
      auto ptr = cell->reg.try_get<qlib::Text::s_ptr>(e);
      if (ptr) {
        auto text = *ptr;
        result.push_back(text);
      }
    }

    {
      auto ptr = cell->reg.try_get<qlib::ViewArea3D::s_ptr>(e);
      if (ptr) {
        auto view_area_3d = *ptr;
        result.push_back(view_area_3d);
      }
    }

    {
      auto ptr = cell->reg.try_get<qlib::SectionArea3D::s_ptr>(e);
      if (ptr) {
        auto section_area_3d = *ptr;
        result.push_back(section_area_3d);
      }
    }

    {
      auto ptr = cell->reg.try_get<qlib::Reference::s_ptr>(e);
      if (ptr) {
        auto ref = *ptr;
        result.push_back(ref);
      }
    }
  }
  return result;
}

std::vector<std::shared_ptr<qlib::Cell>> deepCopyAllRefs(std::vector<std::shared_ptr<qlib::Reference>> refs) {
  std::vector<std::shared_ptr<qlib::Cell>> result;
  for (auto ref : refs) {
    bool is_exist_cell = false;
    for (auto cc : result) {
      if (cc->name == ref->cell->name) {
        ref->cell = cc;
        is_exist_cell = true;
      }
    }
    if (is_exist_cell == false) {
      auto copy_cell = ref->cell->deep_copy_logic();
      ref->cell = copy_cell[0];
      std::set<std::shared_ptr<qlib::Cell>> del_cells;
      for (auto c : copy_cell) {
        for (auto [e, ref] : c->reg.view<qlib::Reference::s_ptr>().each()) {
          for (auto cc : result) {
            if (ref->cell->name == cc->name) {
              del_cells.insert(ref->cell);
              ref->cell = cc;
              break;
            }
          }
        }
      }

      auto _copy_cell = copy_cell;
      copy_cell.clear();
      for (auto c : _copy_cell) {
        auto find_iter = del_cells.find(c);
        if (find_iter == del_cells.end()) {
          copy_cell.push_back(c);
        }
      }

      result.insert(result.end(), copy_cell.begin(), copy_cell.end());
    }
  }
  return result;
}

// 重名校验,若重名在名称后加 (i)
std::string duplicateNameVerify(std::string name, std::vector<std::string> name_list) {
  std::string new_name = name;
  int i = 1;
  for (int k = 0; k < name_list.size(); k++) {
    if (new_name == name_list[k]) {
      new_name = name + "(" + std::to_string(i) + ")";
      i++;
      k = -1;
    }
  }
  return new_name;
};

std::vector<std::any> copyElement(qlib::Cell::s_ptr current_cell, std::vector<entt::entity>& selected_eles) {
  std::vector<std::any> copy_selected;
  auto& current_reg = current_cell->reg;
  for (auto i : selected_eles) {
    auto _poly_ptr = current_reg.try_get<std::shared_ptr<qlib::Polygon>>(i);
    if (_poly_ptr) {
      auto poly_ptr = *_poly_ptr;
      auto copy_poly = poly_ptr->copy();

      copy_selected.push_back(copy_poly);
    }
    auto _rec_ptr = current_reg.try_get<std::shared_ptr<qlib::Rectangle>>(i);
    if (_rec_ptr) {
      auto rec_ptr = *_rec_ptr;
      auto copy_rec = rec_ptr->copy();
      copy_selected.push_back(copy_rec);
    }
    auto _circle_ptr = current_reg.try_get<std::shared_ptr<qlib::Circle>>(i);
    if (_circle_ptr) {
      auto circle_ptr = *_circle_ptr;
      auto copy_circle = circle_ptr->copy();
      copy_selected.push_back(copy_circle);
    }

    {
      auto ptr = current_reg.try_get<std::shared_ptr<qlib::Ellipse>>(i);
      if (ptr) {
        auto elli_ptr = *ptr;
        auto copy_elli = elli_ptr->copy();
        copy_selected.push_back(copy_elli);
      }
    }
    {
      auto ptr = current_reg.try_get<std::shared_ptr<qlib::Fan>>(i);
      if (ptr) {
        auto fan_ptr = *ptr;
        auto copy_fan = fan_ptr->copy();
        copy_selected.push_back(copy_fan);
      }
    }
    {
      auto ptr = current_reg.try_get<std::shared_ptr<qlib::Path>>(i);
      if (ptr) {
        auto line_ptr = *ptr;
        auto copy_line = line_ptr->copy();
        copy_selected.push_back(copy_line);
      }
    }

    {
      auto ptr = current_reg.try_get<std::shared_ptr<qlib::Label>>(i);
      if (ptr) {
        auto label_ptr = *ptr;
        auto copy_label = label_ptr->copy();
        copy_selected.push_back(copy_label);
      }
    }

    {
      auto ptr = current_reg.try_get<std::shared_ptr<qlib::KeyPoint>>(i);
      if (ptr) {
        auto key_point_ptr = *ptr;
        auto copy_key_point = key_point_ptr->copy();
        copy_selected.push_back(copy_key_point);
      }
    }

    {
      auto ptr = current_reg.try_get<std::shared_ptr<qlib::Pin>>(i);
      if (ptr) {
        auto pin_ptr = *ptr;
        auto copy_pin = pin_ptr->copy();
        copy_selected.push_back(copy_pin);
      }
    }

    {
      auto ptr = current_reg.try_get<std::shared_ptr<qlib::Text>>(i);
      if (ptr) {
        auto text_ptr = *ptr;
        auto copy_text = text_ptr->copy();
        copy_selected.push_back(copy_text);
      }
    }

    {
      auto ptr = current_reg.try_get<std::shared_ptr<qlib::Ruler>>(i);
      if (ptr) {
        auto ruler_ptr = *ptr;
        auto copy_ruler = ruler_ptr->copy();
        copy_selected.push_back(copy_ruler);
      }
    }

    {
      auto ptr = current_reg.try_get<std::shared_ptr<qlib::Reference>>(i);
      if (ptr) {
        auto ref_ptr = *ptr;
        auto copy_ref = ref_ptr->copy();
        copy_selected.push_back(copy_ref);
      }
    }
  }
  return copy_selected;
}

std::vector<qlib::Vec2d> calBonndingBox(std::vector<std::any> selected) {
  std::vector<qlib::Vec2d> result;
  qlib::Vec2d min(10e7, 10e7), max(-10e7, -10e7);
  auto cal = [](qlib::Vec2d& min, qlib::Vec2d& max, qlib::Vec2dArray& box) {
    if (min.x > box[0].x)
      min.x = box[0].x;
    if (min.y > box[0].y)
      min.y = box[0].y;

    if (max.x < box[1].x)
      max.x = box[1].x;
    if (max.y < box[1].y)
      max.y = box[1].y;
  };
  for (auto g : selected) {
    const std::type_info& stored_type = g.type();
    if (stored_type == typeid(qlib::Polygon::s_ptr)) {
      qlib::Polygon::s_ptr poly = std::any_cast<qlib::Polygon::s_ptr>(g);
      qlib::Vec2dArray box = poly->bounding_box();
      cal(min, max, box);
    } else if (stored_type == typeid(qlib::Circle::s_ptr)) {
      qlib::Circle::s_ptr circle = std::any_cast<qlib::Circle::s_ptr>(g);
      qlib::Vec2dArray box = circle->bounding_box();
      cal(min, max, box);
    } else if (stored_type == typeid(qlib::Ellipse::s_ptr)) {
      qlib::Ellipse::s_ptr elli = std::any_cast<qlib::Ellipse::s_ptr>(g);
      qlib::Vec2dArray box = elli->bounding_box();
      cal(min, max, box);
    } else if (stored_type == typeid(qlib::Rectangle::s_ptr)) {
      qlib::Rectangle::s_ptr rec = std::any_cast<qlib::Rectangle::s_ptr>(g);
      qlib::Vec2dArray box = rec->bounding_box();
      cal(min, max, box);
    } else if (stored_type == typeid(qlib::Fan::s_ptr)) {
      qlib::Fan::s_ptr fan = std::any_cast<qlib::Fan::s_ptr>(g);
      qlib::Vec2dArray box = fan->bounding_box();
      cal(min, max, box);
    } else if (stored_type == typeid(qlib::Path::s_ptr)) {
      qlib::Path::s_ptr line = std::any_cast<qlib::Path::s_ptr>(g);
      qlib::Vec2dArray box = line->bounding_box();
      cal(min, max, box);
    } else if (stored_type == typeid(qlib::Text::s_ptr)) {
      qlib::Text::s_ptr text = std::any_cast<qlib::Text::s_ptr>(g);
      qlib::Vec2dArray box = text->bounding_box();
      cal(min, max, box);
    } else if (stored_type == typeid(qlib::Label::s_ptr)) {
      qlib::Label::s_ptr label = std::any_cast<qlib::Label::s_ptr>(g);
      qlib::Vec2dArray box = label->bounding_box();
      cal(min, max, box);
    } else if (stored_type == typeid(qlib::KeyPoint::s_ptr)) {
      qlib::KeyPoint::s_ptr key_point = std::any_cast<qlib::KeyPoint::s_ptr>(g);
      qlib::Vec2dArray box = key_point->bounding_box();
      cal(min, max, box);
    } else if (stored_type == typeid(qlib::Pin::s_ptr)) {
      qlib::Pin::s_ptr pin = std::any_cast<qlib::Pin::s_ptr>(g);
      qlib::Vec2dArray box = pin->bounding_box();
      cal(min, max, box);
    } else if (stored_type == typeid(qlib::Ruler::s_ptr)) {
      qlib::Ruler::s_ptr ruler = std::any_cast<qlib::Ruler::s_ptr>(g);
      qlib::Vec2dArray box = ruler->bounding_box();
      cal(min, max, box);
    } else if (stored_type == typeid(qlib::ViewArea3D::s_ptr)) {
      qlib::ViewArea3D::s_ptr view_area_3d = std::any_cast<qlib::ViewArea3D::s_ptr>(g);
      qlib::Vec2dArray box = view_area_3d->bounding_box();
      cal(min, max, box);
    } else if (stored_type == typeid(qlib::SectionArea3D::s_ptr)) {
      qlib::SectionArea3D::s_ptr section_area_3d = std::any_cast<qlib::SectionArea3D::s_ptr>(g);
      qlib::Vec2dArray box = section_area_3d->bounding_box();
      cal(min, max, box);
    } else if (stored_type == typeid(qlib::Ruler::s_ptr)) {
      qlib::Ruler::s_ptr ruler = std::any_cast<qlib::Ruler::s_ptr>(g);
      qlib::Vec2dArray box = ruler->bounding_box();
      cal(min, max, box);
    } else if (stored_type == typeid(qlib::Reference::s_ptr)) {
      qlib::Reference::s_ptr ref = std::any_cast<qlib::Reference::s_ptr>(g);
      qlib::Vec2dArray box;
      box.push_back(qlib::Vec2d());
      box.push_back(qlib::Vec2d());
      ref->bounding_box(box[0], box[1]);
      cal(min, max, box);
    }
  }
  result.push_back(min);
  result.push_back(max);
  return result;
}

void translateGraph(std::vector<std::any> graphs, qlib::Vec2d offset) {
  for (auto i : graphs) {
    const std::type_info& stored_type = i.type();
    if (stored_type == typeid(qlib::Polygon::s_ptr)) {
      qlib::Polygon::s_ptr poly = std::any_cast<qlib::Polygon::s_ptr>(i);
      poly->translate(offset.x, offset.y);
    } else if (stored_type == typeid(qlib::Circle::s_ptr)) {
      qlib::Circle::s_ptr circle = std::any_cast<qlib::Circle::s_ptr>(i);
      circle->translate(offset.x, offset.y);
    } else if (stored_type == typeid(qlib::Ellipse::s_ptr)) {
      qlib::Ellipse::s_ptr elli = std::any_cast<qlib::Ellipse::s_ptr>(i);
      elli->translate(offset.x, offset.y);
    } else if (stored_type == typeid(qlib::Rectangle::s_ptr)) {
      qlib::Rectangle::s_ptr rec = std::any_cast<qlib::Rectangle::s_ptr>(i);
      rec->translate(offset.x, offset.y);
    } else if (stored_type == typeid(qlib::Fan::s_ptr)) {
      qlib::Fan::s_ptr fan = std::any_cast<qlib::Fan::s_ptr>(i);
      fan->translate(offset.x, offset.y);
    } else if (stored_type == typeid(qlib::Path::s_ptr)) {
      qlib::Path::s_ptr line = std::any_cast<qlib::Path::s_ptr>(i);
      line->translate(offset.x, offset.y);
    } else if (stored_type == typeid(qlib::Text::s_ptr)) {
      qlib::Text::s_ptr text = std::any_cast<qlib::Text::s_ptr>(i);
      text->translate(offset.x, offset.y);
    } else if (stored_type == typeid(qlib::Label::s_ptr)) {
      qlib::Label::s_ptr label = std::any_cast<qlib::Label::s_ptr>(i);
      label->translate(offset.x, offset.y);
    } else if (stored_type == typeid(qlib::KeyPoint::s_ptr)) {
      qlib::KeyPoint::s_ptr key_point = std::any_cast<qlib::KeyPoint::s_ptr>(i);
      key_point->translate(offset.x, offset.y);
    } else if (stored_type == typeid(qlib::Pin::s_ptr)) {
      qlib::Pin::s_ptr pin = std::any_cast<qlib::Pin::s_ptr>(i);
      pin->translate(offset.x, offset.y);
    } else if (stored_type == typeid(qlib::Ruler::s_ptr)) {
      qlib::Ruler::s_ptr ruler = std::any_cast<qlib::Ruler::s_ptr>(i);
      ruler->translate(offset.x, offset.y);
    } else if (stored_type == typeid(qlib::Reference::s_ptr)) {
      qlib::Reference::s_ptr ref = std::any_cast<qlib::Reference::s_ptr>(i);
      ref->origin += offset;
    }
  }
}

bool pointIsSegmentInternal(qlib::Vec2d& point, qlib::Vec2d& segment_1, qlib::Vec2d& segment_2, double scale) {
  double dis_1 = (point - segment_1).length();
  double dis_2 = (point - segment_2).length();
  double dis = (segment_1 - segment_2).length();
  double ret = abs(dis - dis_1 - dis_2);
  if (ret < (1e-2 / scale)) {
    return true;
  } else {
    return false;
  }
}

double distance(const qlib::Vec2d& a, const qlib::Vec2d& b) {
  return std::sqrt((b.x - a.x) * (b.x - a.x) + (b.y - a.y) * (b.y - a.y));
}
bool findPointsOnLine(const qlib::Vec2d& A, const qlib::Vec2d& B, const qlib::Vec2d& C, qlib::Vec2d& Q1, qlib::Vec2d& Q2, double scale) {
  double slope_q1;
  double slope_q2;
  double q1_x;
  double q2_x;
  double q1_y;
  double q2_y;

  double x_diff = std::fabs(A.x - B.x);
  if (x_diff < (10e-3 / scale)) {     // 垂线
    double d = std::fabs(C.x - A.x);  // 点到垂线的距离
    q1_x = A.x;
    q2_x = A.x;
    q1_y = C.y + d;
    q2_y = C.y - d;
  } else {

    // 计算AB的直线方程 y = kx + b;
    double slope_ab = (B.y - A.y) / (B.x - A.x);
    double b_ab = A.y - slope_ab * A.x;

    if (slope_ab != 0.0) {
      // 计算垂线的斜率
      double slope_cp = -(1 / slope_ab);
      slope_q1 = (slope_cp + 1) / (1 - slope_cp);  // 偏45度
      slope_q2 = (slope_cp - 1) / (1 + slope_cp);
    }

    if (slope_ab == 0.0)  // 水平的线
    {
      slope_q1 = 1;  // 偏45度
      slope_q2 = -1;
    }

    double b_q1 = C.y - slope_q1 * C.x;
    double b_q2 = C.y - slope_q2 * C.x;

    q1_x = (b_ab - b_q1) / (slope_q1 - slope_ab);
    q2_x = (b_ab - b_q2) / (slope_q2 - slope_ab);

    // 代入ab方程求y
    q1_y = slope_ab * q1_x + b_ab;
    q2_y = slope_ab * q2_x + b_ab;

    if (slope_ab != 0.0)  // 特殊情况处理
    {
      double slope_cp = -(1 / slope_ab);
      double diff_slope_cp_pos = std::fabs(slope_cp - 1);  // 等于 1
      if (diff_slope_cp_pos < 1e-3)                        //鼠标点到线段的垂线为45度，那么c-q1或者cq2有一条线是垂线
      {
        q1_x = C.x;

        // 代入ab方程求y
        q1_y = slope_ab * q1_x + b_ab;
      }

      double diff_slope_cp_neg = std::fabs(slope_cp - (-1));  // 等于 -1
      if (diff_slope_cp_neg < 1e-3)                           //鼠标点到线段的垂线为45度，那么c-q1或者cq2有一条线是垂线
      {
        q2_x = C.x;

        // 代入ab方程求y
        q2_y = slope_ab * q2_x + b_ab;
      }
    }
  }

  qlib::Vec2d point_1(q1_x, q1_y);
  qlib::Vec2d point_2(q2_x, q2_y);

  double distance_1 = distance(A, point_1);
  double distance_2 = distance(A, point_2);

  if (distance_1 > distance_2) {
    Q1 = qlib::Vec2d(q2_x, q2_y);
    Q2 = qlib::Vec2d(q1_x, q1_y);
  } else {
    Q1 = qlib::Vec2d(q1_x, q1_y);
    Q2 = qlib::Vec2d(q2_x, q2_y);
  }

  // 判断是否越界
  double min_x, min_y;
  double max_x, max_y;
  if (A.x <= B.x) {
    min_x = A.x;
    max_x = B.x;
  } else {
    min_x = B.x;
    max_x = A.x;
  }

  if (A.y <= B.y) {
    min_y = A.y;
    max_y = B.y;
  } else {
    min_y = B.y;
    max_y = A.y;
  }

  if (Q1.x < min_x || Q1.x > max_x) {
    return false;
  }

  if (Q1.y < min_y || Q1.y > max_y) {
    return false;
  }

  if (Q2.x < min_x || Q2.x > max_x) {
    return false;
  }

  if (Q2.y < min_y || Q2.y > max_y) {
    return false;
  }

  return true;
}

std::vector<qlib::Vec2<double>> calArrayPosition(double start_x, double start_y, int row, int col, qlib::Vec2<double> row_vector,
                                                 qlib::Vec2<double> col_vector) {
  std::vector<qlib::Vec2<double>> position;
  for (int i = 0; i < row; i++) {
    for (int j = 0; j < col; j++) {
      double x = start_x + j * col_vector.x + i * row_vector.x;
      double y = start_y + i * row_vector.y + j * col_vector.y;
      position.push_back(qlib::Vec2<double>(x, y));
    }
  }
  return position;
}

// 直线斜率 (平行X轴: 0, 平行y轴: nullptr)
std::shared_ptr<double> getSlope(qlib::Vec2d p1, qlib::Vec2d p2) {
  std::shared_ptr<double> reslut = nullptr;
  double x1 = p1.x;
  double x2 = p2.x;
  double y1 = p1.y;
  double y2 = p2.y;
  double delta_x = x2 - x1;
  if (delta_x != 0)
    reslut = std::make_shared<double>((y2 - y1) / delta_x);

  return reslut;
};

bool lineIntersectSeg(qlib::Vec2d p, qlib::Vec2d q, qlib::Vec2d A, qlib::Vec2d B, qlib::Vec2d& inter_point) {
  std::shared_ptr<double> slope_1 = getSlope(p, q);
  std::shared_ptr<double> slope_2 = getSlope(A, B);
  std::vector<std::shared_ptr<double>> line_c_last = slopeAndIntercept(p, q, slope_1);
  std::vector<std::shared_ptr<double>> line_last_d = slopeAndIntercept(A, B, slope_2);

  // 平行线没有交点
  if (!line_c_last[0] && !line_last_d[0])
    return false;
  if (line_c_last[0] && line_last_d[0]) {
    if (abs(*line_c_last[0] - *line_last_d[0]) < 10e-7)
      return false;
  }

  inter_point = calculateIntersectionPoint(line_c_last, line_last_d);
  {
    double dis_1 = (p - inter_point).length();
    double dis_2 = (q - inter_point).length();
    double dis = (p - q).length();

    if (abs(dis - dis_1 - dis_2) > 10e-5)
      return false;
  }

  {
    double dis_1 = (A - inter_point).length();
    double dis_2 = (B - inter_point).length();
    double dis = (A - B).length();

    if (abs(dis - dis_1 - dis_2) > 10e-5)
      return false;
  }

  return true;
}

// 直线斜率和y交点 直线表达式 y= slope * x + intercept
std::vector<std::shared_ptr<double>> slopeAndIntercept(qlib::Vec2d p1, qlib::Vec2d p2, std::shared_ptr<double> s) {
  double x1 = p1.x;
  double x2 = p2.x;
  double y1 = p1.y;
  double y2 = p2.y;
  std::shared_ptr<double> slope = nullptr;
  if (s != nullptr) {
    slope = std::make_shared<double>(*s);
  }

  std::shared_ptr<double> intercept = nullptr;
  if (slope != nullptr)
    intercept = std::make_shared<double>(y1 - (*slope) * x1);
  if (slope == nullptr) {
    intercept = std::make_shared<double>(x1);
  }
  std::vector<std::shared_ptr<double>> result;
  result.push_back(slope);
  result.push_back(intercept);
  return result;
}

qlib::Vec2d calculateIntersectionPoint(std::vector<std::shared_ptr<double>> line_a, std::vector<std::shared_ptr<double>> line_b) {
  std::shared_ptr<double> a = line_a[0];
  std::shared_ptr<double> b = line_b[0];
  std::shared_ptr<double> c = line_a[1];
  std::shared_ptr<double> d = line_b[1];
  double px;
  double py;
  if (a == nullptr) {
    px = *c;
    py = *b * px + *d;
  } else if (b == nullptr) {
    px = *d;
    py = *a * px + *c;
  } else {
    px = (*d - *c) / (*a - *b);
    py = *a * px + *c;
  }

  return qlib::Vec2d(px, py);
};

qlib::Vec2d GetFootOfPerpendicular(const qlib::Vec2d& pt,     // 直线外一点
                                   const qlib::Vec2d& begin,  // 直线开始点
                                   const qlib::Vec2d& end)    // 直线结束点
{
  qlib::Vec2d retVal;

  double dx = begin.x - end.x;
  double dy = begin.y - end.y;
  if (abs(dx) < 0.00000001 && abs(dy) < 0.00000001) {
    retVal = begin;
    return retVal;
  }

  double u = (pt.x - begin.x) * (begin.x - end.x) + (pt.y - begin.y) * (begin.y - end.y);
  u = u / ((dx * dx) + (dy * dy));

  retVal.x = begin.x + u * dx;
  retVal.y = begin.y + u * dy;

  return retVal;
}

std::vector<int> getAroundIndex(int index, int total, int length, int space) {
  std::vector<int> result;
  for (int i = 0; i < length; i++) {
    int temp = index - space + i;
    if (temp == index)
      continue;
    if (temp < 0) {
      temp += total + 1;
    } else if (temp > total) {
      temp -= total + 1;
    }
    result.emplace_back(temp);
  }

  return result;
};

double angle_direction(qlib::Vec2d p1, qlib::Vec2d p2) {
  double dx = p2.x - p1.x;
  double dy = p2.y - p1.y;
  if (abs(dy) < 0.0001) {
    if (dx > 0)
      return 0;
    if (dx < 0)
      return M_PI;
  }
  if (abs(dx) < 0.0001) {
    if (dy > 0)
      return M_PI / 2;
    if (dy < 0)
      return (M_PI * 3) / 2;
  }
  double angle = atan(abs(dy / dx));
  if (dy > 0) {
    if (dx > 0)
      // 第一象限
      return angle;
    if (dx < 0)
      // 第二象限
      return M_PI - angle;
  }
  if (dy < 0) {
    if (dx < 0)
      // 第三象限
      return M_PI + angle;
    if (dx > 0)
      // 第四象限
      return 2 * M_PI - angle;
  }
  return 0;
};

std::vector<qlib::Vec2d> pointExtendToLine(qlib::Vec2d pos, double direct, double length) {
  // """ 按点位和方向生成一定长度的线段
  // args:
  //     pos: 点位
  //     direct: 方向角度, 弧度
  //     length: 长度
  // return:
  //     line: 线段
  // """
  std::vector<qlib::Vec2d> line;
  double dx = length * cos(direct);
  double dy = length * sin(direct);
  line.push_back(pos);
  line.push_back(qlib::Vec2d(pos.x + dx, pos.y + dy));
  return line;
};

uint32_t UpdateCellInstanceNameMaxId(std::shared_ptr<qlib::Cell> cell) {
  uint32_t max_id = 0;
  for (auto [e, ref] : cell->reg.view<qlib::Reference::s_ptr>().each()) {
    auto str = QString::fromStdString(ref->getInstanceName());
    if (str.length() > 0) {
      if (str[0] == "U") {
        auto id = str.mid(1, str.length() - 1).toInt();
        if (id > max_id)
          max_id = id;
      }
    }
  }
  return ++max_id;
};

std::vector<qlib::Vec2d> connectLine(std::vector<std::shared_ptr<qlib::Path>>& lines) {
  std::vector<qlib::Vec2d> result;
  std::list<std::shared_ptr<qlib::Path>> sort_lines;
  std::set<std::shared_ptr<qlib::Path>> deal_with_lines;
  deal_with_lines.insert(lines[0]);
  sort_lines.push_back(lines[0]);
  result = lines[0]->spine.points;
  std::map<qlib::Vec2d, std::shared_ptr<qlib::Path>> point_to_lines;
  auto find_line = [&lines, &deal_with_lines](qlib::Vec2d point) -> std::shared_ptr<qlib::Path> {
    for (auto i : lines) {
      if (deal_with_lines.count(i))
        continue;
      auto start = qlib::gds_utils::roundFunc(i->spine.points[0], 1000);
      auto end = qlib::gds_utils::roundFunc(i->spine.points[i->spine.points.size() - 1], 1000);
      if (start == point || end == point) {
        deal_with_lines.insert(i);
        return i;
      }
    }
    return nullptr;
  };
  while (deal_with_lines.size() != lines.size()) {
    //处理首点
    {
      auto deal_p = qlib::gds_utils::roundFunc(result[0], 1000);
      auto find_line_1 = find_line(deal_p);
      if (find_line_1) {
        //首-首
        if (qlib::gds_utils::roundFunc(find_line_1->spine.points[0], 1000) == deal_p) {
          std::vector<qlib::Vec2d> temp = result;
          result.clear();
          for (int i = find_line_1->spine.points.size() - 1; i >= 0; i--) {
            result.push_back(find_line_1->spine.points[i]);
          }
          result.pop_back();
          result.insert(result.end(), temp.begin(), temp.end());
          sort_lines.push_front(find_line_1);
        }
        //尾-首
        if (qlib::gds_utils::roundFunc(find_line_1->spine.points.back(), 1000) == deal_p) {
          std::vector<qlib::Vec2d> temp = result;
          result.clear();
          result.insert(result.end(), find_line_1->spine.points.begin(), find_line_1->spine.points.end());
          result.pop_back();
          result.insert(result.end(), temp.begin(), temp.end());
          sort_lines.push_front(find_line_1);
        }
        continue;
      }
    }

    //处理尾点
    {
      auto deal_p = qlib::gds_utils::roundFunc(result.back(), 1000);
      auto find_line_2 = find_line(deal_p);
      if (find_line_2) {
        //尾-首
        if (qlib::gds_utils::roundFunc(find_line_2->spine.points[0], 1000) == deal_p) {
          result.pop_back();
          result.insert(result.end(), find_line_2->spine.points.begin(), find_line_2->spine.points.end());
          sort_lines.push_back(find_line_2);
        }
        //尾-尾
        if (qlib::gds_utils::roundFunc(find_line_2->spine.points.back(), 1000) == deal_p) {
          result.pop_back();
          for (int i = find_line_2->spine.points.size() - 1; i >= 0; i--) {
            result.push_back(find_line_2->spine.points[i]);
          }
          sort_lines.push_back(find_line_2);
        }
        continue;
      }
    }
  }
  lines.clear();
  lines.insert(lines.end(), sort_lines.begin(), sort_lines.end());
  return result;
};
void UpdateCellMaxPinId(std::shared_ptr<qlib::Cell> cell) {
  //计算算pin的最大编号
  cell->max_pin_id = 0;
  for (auto [e, pin] : cell->reg.view<qlib::Pin::s_ptr>().each()) {
    {
      QStringList pin_text_list = QString::fromStdString(pin->text).split(",");
      auto id = pin_text_list[0].toInt();
      if (id > cell->max_pin_id)
        cell->max_pin_id = id;
    }
  }
}
}  // namespace qbe::auxiliary